package cn.iocoder.yudao.framework.pay.core.client.impl.epayments;

import cn.hutool.core.map.MapUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.pay.core.client.impl.epayments.model.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import java.util.List;
import java.util.Map;

import jodd.util.StringUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

/**
 * 请求支付系统的接口服务类,文档地址：https://www.kiwifast.com/doc/#api-API-NewJSAPI
 *
 * @author 王广帅
 * @since 2024/1/23 8:41
 */
@Slf4j
public class DefaultEPaymentsClient {

    private String payUrl = "https://www.kiwifast.com/api/v1/info/smartpay";

    private EPaymentsClientConfig appConfig;

    public DefaultEPaymentsClient(EPaymentsClientConfig appConfig) {
        this.appConfig = appConfig;
    }

    @SneakyThrows
    public <T extends BaseEPayResult> T genUrlResult(BaseEPayParam param, Class<T> clazz) {
        T result;
        if (!param.checkService()) {
            log.info("service字段必填, 不能为空");
            result = clazz.newInstance();
            result.setCode("500");
            result.setMessage("service字段必填, 不能为空");
            return result;
        }
        EPaymentsSignatureManager signatureManager = new EPaymentsSignatureManager();
        String pathParam = signatureManager.getRequestParam(param, appConfig);
        String url = this.payUrl + "?" + pathParam;
        log.info("支付请求完整url: {}", url);
        result = clazz.newInstance();
        result.setCode("0");
        result.setContent(url);
        return result;
    }


    @SneakyThrows
    public <T extends BaseEPayResult> T execute(BaseEPayParam param, Class<T> clazz) {
        return execute(param, null, clazz);
    }

    @SneakyThrows
    public <T extends BaseEPayResult> T execute(BaseEPayParam param, Map<String, String> headers, Class<T> clazz) {
        T result;
        if (!param.checkService()) {
            log.info("service字段必填, 不能为空");
            result = clazz.newInstance();
            result.setCode("500");
            result.setMessage("service字段必填, 不能为空");
            return result;
        }
        EPaymentsSignatureManager signatureManager = new EPaymentsSignatureManager();
        String pathParam = signatureManager.getRequestParam(param, appConfig);
        String url = this.payUrl + "?" + pathParam;
        log.info("支付请求完整url: {}", url);
        HttpRequest request = HttpUtil.createGet(url);
        if (MapUtil.isNotEmpty(headers)) {
            for (String key : headers.keySet()) {
                request.header(key, headers.get(key));
            }
        }
        HttpResponse response = request.execute();
        String resultStr = response.body();

        if (StringUtil.isNotEmpty(resultStr)) {
            if (JSONUtil.isTypeJSON(resultStr)) {
                JSONObject jsonObject = JSONObject.parseObject(resultStr);
                String signValue = jsonObject.getString(EPaymentsSignatureManager.SIGNATURE);
                result = jsonObject.toJavaObject(clazz);
                if (result.checkSuccess() && StringUtil.isNotEmpty(signValue)) {
                    boolean signResult = signatureManager.checkSign(jsonObject, signValue, appConfig);
                    if (!signResult) {
                        result = clazz.newInstance();
                        result.setCode("500");
                        result.setMessage("响应结果签名校验失败");
                    }
                }
            } else {
                log.info(resultStr);
                result = clazz.newInstance();
                result.setCode("0");
                result.setContent(resultStr);
            }
        } else {
            log.info("epayments execute command {} 失败, 返回结果为空, url = {}", param.getService(), url);
            result = clazz.newInstance();
            result.setCode("500");
            result.setMessage(String.format("execute command %s，请求支付机构异常", param.getService()));
        }
        return result;
    }

    public void checkSign(JSONObject obj) {
        EPaymentsSignatureManager signatureManager = new EPaymentsSignatureManager();
        String signValue = obj.getString(EPaymentsSignatureManager.SIGNATURE);
        boolean signResult = signatureManager.checkSign(obj, signValue, appConfig);
        if (!signResult) {
            log.error("聚合支付响应结果签名校验失败, obj = {}", obj.toJSONString());
            throw new IllegalArgumentException("聚合支付响应结果签名校验失败");
        }
    }

}
